<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button id="bt">按钮</button>
    <script>
        /*
            观察者模式（发布订阅模式）--框架底层---事件系统（元素添加事件）

            只要关注了他， 他有什么消息 就会通知你


            按钮-添加点击事件--关注了按钮的 的被点击的 行为，，一旦按钮被动点击， 事件处理函数就会被执行
        */
        var bt = document.querySelector("#bt");

        // 添加一个观察者，观察者，要观察 click事件，，click事件只要被触发，系统 后面的函数被调用（通知）

        //两个函数在观察 click事件

        // 添加一个观察者
        let fn = function () {
            console.log('click 1');
        }
        /* 
        
        bt 内部 有一个对象 ，存了 所有事件名和 事件处理函数

        第一次添加观察者，给对象，添加一个属性，属性名是 事件名，属性值 是数组，数组存 事件处理函数
        不是第一次添加观察者，根据数据名找到 数据，往数组里面添加元素（事件处理函数）
           {
             click: [fn,fn2],
             mouseover:[fn3]
           }
        
        */
        bt.addEventListener('click', fn);
        bt.addEventListener('click', function () {
            console.log('click 2');
        })

        bt.addEventListener('mouseover', function (evt) { });



        // 删除观察着
        // bt.removeEventListener('click', fn)


        // // 触发一个事情-通知所有观察者
        // setTimeout(() => {
        //     bt.dispatchEvent(new Event('click'));
        // }, 1000);



        // EventBus 事件总线--
        class EventBus {
            // 定义空的对象 ，存 事件名和 事件处理函数
            obj = {}
            addEventListener(type, fn) {

                // 判断 obj 是否有 type变量的值  属性
                // obj.a//->undefined 
                // if (obj.hasOwnerPropterty(type) == false) {
                //     console.log('没有 这个属性');
                // }

                // 第一次添加观察者，给对象，添加一个属性，属性名是 事件名，
                // 属性值 是数组，数组存 事件处理函数

                if (this.obj[type] === undefined) {
                    console.log('没有 这个属性');
                    this.obj[type] = [fn]
                } else {
                    // 不是第一次添加观察者，根据数据名找到 数据，
                    // 往数组里面添加元素（事件处理函数）
                    this.obj[type].push(fn)
                }
                console.log(this.obj);

            }

            removeEventListener(type, fn) {
                // 移出--删除 type变量的值为属性 的属性值-数组 中的元素
                console.log(this.obj[type]);

                // 删除数组中 元素 和fn 相等的那个元素

                //找到fn的下标
                let i = this.obj[type].findIndex(v => v === fn);
                // let i = this.obj[type].indexOf(fn);
                //删除i位置的元素
                this.obj[type].splice(i, 1)

                console.log(this.obj[type]);

            }
            //通知所有的观察者--派发事件
            dispatch(type, data) {
                // 通知 所有观察a事件的观察着
                console.log(this.obj[type]);

                // 遍历 数组中所有 函数，调用
                this.obj[type].forEach(element => {
                    console.log(element);

                    // 调用--传入 参数数据
                    element(data)
                });
            }
        }

        let eb = new EventBus();
        // eb.obj = {a:[fn]}

        eb.addEventListener('a', function (evt) {
            console.log('a 1 fn');
            console.log(evt);
        })
        let fn2 = function (evt) {
            console.log('a 2 fn');
            console.log(evt);
        }

        eb.addEventListener('a', fn2)

        // eb.removeEventListener('a', fn2)

        setTimeout(() => {

            // 通知 所有观察a事件的观察着
            eb.dispatch('a', '这是文章的内容111')

        }, 1000);
    </script>

</body>

</html>